home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Collection of Tools & Utilities
/
Collection of Tools and Utilities.iso
/
asmutil
/
afloat.zip
/
F_ADD.ASM
< prev
next >
Wrap
Assembly Source File
|
1988-03-14
|
4KB
|
178 lines
PAGE ,132
;----------------------------------------------------------
; F_ADD -- version for use with assembly language programs
;
; Copyright Bob Kline 1988
;
; Purpose:
; Add two single-precision floating-point numbers.
;
; Input:
; DX:AX and CX:BX contain the two 4-byte reals
; to be added in IEEE format.
;
; Output:
; Result (IEEE) is single-precision real in DX:AX
;
; Other registers affected:
; BX, CX, SI, DI, BP
;
; Other procedures called:
; F_SUB
;
; Comments:
; Sets external variable _errno to ERANGE if over-
; flow occurs. If a calling routine will be testing
; _errno, it must first reset the variable to zero
; to be sure that an error code is not left over
; from some previous call. If the signs of the two
; operands differ the negative number is placed in
; CX:BX, the sign removed, and F_SUB is called.
;----------------------------------------------------------
.MODEL SMALL
PUBLIC F_ADD
EXTRN _errno:WORD,F_SUB:PROC
ERANGE EQU 34
.CODE
F_ADD PROC
; before doing anything else, see if one of the operands
; is zero
MOV SI,CX
OR SI,BX
JZ DONE
MOV SI,DX
OR SI,AX
JNZ CHKSGN
MOV AX,BX
MOV DX,CX
RET
; check the sign
CHKSGN: MOV SI,DX
XOR SI,CX
JNS SAME_SIGNS
; signs are different -- put the one with the
; minus sign in the subtrahend position,
; remove its sign, and use F_SUB
OR DX,DX
JNS NOSWAP
XCHG DX,CX
XCHG AX,BX
NOSWAP: AND CX,7FFFh
CALL F_SUB
DONE: RET
; sign same for both -- save it
SAME_SIGNS:
MOV SI,DX
AND SI,8000h
PUSH SI
; unpack exponent and remove bias
MOV DI,DX
MOV SI,CX
SHL DX,1
SHL CX,1
XCHG DH,DL
XCHG CH,CL
XOR DH,DH
XOR CH,CH
SUB DX,127
SUB CX,127
XCHG DI,DX
XCHG SI,CX
; unpack the mantissas & slide over to the left
; one position so we'll have elbowroom to catch
; any lost low bit for rounding
AND DX,7Fh
AND CX,7Fh
OR DX,80h
OR CX,80h
SHL AX,1
RCL DX,1
SHL BX,1
RCL CX,1
; use BP instead of CX for high word of 2nd operand so
; we can use CX for shift counting
MOV BP,CX
; if exponents are equal, no adjustment necessary
CMP DI,SI
JE MATCHED
; otherwise make first operand the larger of the two
JG ADJUST
XCHG DX,BP
XCHG AX,BX
XCHG DI,SI
; make the exponents equal
ADJUST: MOV CX,DI
SUB CX,SI
; if the second number is so much smaller than than first
; that adding it in will not make any difference, don't bother
CMP CX,24
JA SHIFTBACK
; shift lower number to the right
LOOP1: SHR BP,1
RCR BX,1
LOOP LOOP1
; the exponents now match -- add the mantissas
MATCHED:
ADD AX,BX
ADC DX,BP
; see if we gained a position during addition --
; shift right once if we did & increment exponent
TEST DX,200h
JZ SHIFTBACK
SHR DX,1
RCR AX,1
INC DI
; now we undo that left shift we did up above to make
; room for a rounding bit -- and here's where we do
; the rounding
SHIFTBACK:
ADD AX,1
ADC DX,0
SHR DX,1
RCR AX,1
; make the top bit of the mantissa invisible -- it's understood
AND DX,7Fh
; restore exponent bias
MOV BX,DI
ADD BX,127
; test for valid exponent and re-pack
OR BH,BH
JZ EXP_OK
MOV _errno,ERANGE
XOR BH,BH
EXP_OK: XCHG BH,BL
SHR BX,1
OR DX,BX
; get sign back and we're done
POP CX
OR DX,CX
RET
F_ADD ENDP
END